package com.chenfei.sharding.jdbc.strategy;

import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm;
import com.google.common.collect.Range;

import java.util.Collection;
import java.util.LinkedHashSet;

/**
 * @author chenfei
 * @description
 * @since 2018/3/30
 */
public class DatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Integer> {
    @Override
    public String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) {
        for (String node : availableTargetNames) {
            if (node.endsWith(schemaIndex(shardingValue.getValue()))) {
                return node;
            }
        }
        throw new UnsupportedOperationException();
    }

    @Override
    public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
        for (Integer value : shardingValue.getValues()) {
            String index = schemaIndex(value);
            for (String node : availableTargetNames) {
                if (node.endsWith(index)) {
                    result.add(node);
                }
            }
        }
        return result;
    }

    @Override
    public Collection<String> doBetweenSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
        Range<Integer> range = shardingValue.getValueRange();
        for (Integer value = range.lowerEndpoint(); value <= range.upperEndpoint(); value++) {
            String index = schemaIndex(value);
            for (String node : availableTargetNames) {
                if (node.endsWith(index)) {
                    result.add(node);
                }
            }
        }
        return result;
    }

    /**
     * 数据库索引规则, 取模
     * @param shardingValue shardingValue
     * @return 索引
     */
    private String schemaIndex(final Integer shardingValue){
        return "_" + (shardingValue % 2);
    }
}
